﻿// /*------------------------------------------------------------
// 工程名:    Ensemble
// 文件名:    ReflectionHelper.cs
// 编写人:    yhh
// 编写日期: 下午 6:17
// -------------------------------------------------------------*/

using System;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Ensemble
{
    public static class ReflectionHelper
    {
        public static string GetShortAssemblyName(this AssemblyName assemblyName)
        {
            return assemblyName.FullName.Split(',')[0];
        }

        public static string GetShortAssemblyName(this Assembly assembly)
        {
            return assembly.FullName.Split(',')[0];
        }

        public static string GetShortAssemblyName(string assemblyName)
        {
            return assemblyName.Split(',')[0];
        }

        /// <summary>
        /// 返回某种类型的字符串
        /// </summary>
        public static string GetTypeCSCodeName(this Type type, bool shortName = false)
        {
            var typeStr = new StringBuilder();

            if (type.IsGenericParameter)
            {
                return type.Name;
            }
            if (type.IsArray)
            {
                typeStr.Append(GetTypeCSCodeName(type.GetElementType(), shortName));
                typeStr.Append('[');
                typeStr.Append(',', type.GetArrayRank() - 1);
                typeStr.Append(']');
            }
            else
            {
                var typeInfo = type.GetTypeInfo();
                var genArgs = typeInfo.IsGenericType ? typeInfo.GenericTypeParameters : null;

                if (type.IsNested)
                {
                    var declType = type.DeclaringType;
                    var declTypeInfo = declType.GetTypeInfo();

                    if (declTypeInfo.IsGenericTypeDefinition)
                    {
                        Array.Resize(ref genArgs,declTypeInfo.GenericTypeArguments.Length);
                        declType = declTypeInfo.MakeGenericType(genArgs);
                        declTypeInfo = declType.GetTypeInfo();
                        genArgs = type.GenericTypeArguments.Skip(genArgs.Length).ToArray();
                    }
                    var parentName = GetTypeCSCodeName(declType, shortName);

                    var nestedNameToken = shortName ? type.Name.Split('+') : type.FullName.Split('+');
                    var nestedName = nestedNameToken[nestedNameToken.Length - 1];

                    var genTypeSepIndex = nestedName.IndexOf("[[", StringComparison.Ordinal);
                    if (genTypeSepIndex != -1) nestedName = parentName.Substring(0, genTypeSepIndex);
                    genTypeSepIndex = nestedName.IndexOf('`');
                    if (genTypeSepIndex != -1) nestedName = nestedName.Substring(0, genTypeSepIndex);

                    typeStr.Append(parentName);
                    typeStr.Append(".");
                    typeStr.Append(nestedName);
                }
                else
                {
                    if (shortName)
                    {
                        typeStr.Append(type.Name.Split(new[] {'`'}, StringSplitOptions.RemoveEmptyEntries)[0]
                            .Replace('+', '.'));
                    }
                    else
                    {
                        typeStr.Append(type.FullName.Split(new[] {'`'}, StringSplitOptions.RemoveEmptyEntries)[0]
                            .Replace('+', '.'));
                    }
                }

                if (genArgs != null && genArgs.Length > 0)
                {
                    if (typeInfo.IsGenericTypeDefinition)
                    {
                        typeStr.Append('<');
                        typeStr.Append(',', genArgs.Length - 1);
                        typeStr.Append('>');
                    }
                    else if (typeInfo.IsGenericType)
                    {
                        typeStr.Append('<');
                        for (int i = 0; i < genArgs.Length; i++)
                        {
                            typeStr.Append(GetTypeCSCodeName(genArgs[i], shortName));
                            if (i < genArgs.Length - 1)
                            {
                                typeStr.Append(',');
                            }
                        }
                        typeStr.Append('>');
                    }
                }
            }

            return typeStr.Replace('+', '.').ToString();
        }
    }
}